package com.shanghe.house.service;

import java.time.LocalDateTime;
import java.util.List;

import org.springframework.beans.BeanUtils;
import org.springframework.scheduling.support.CronExpression;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.shanghe.house.dto.TimerDTO;
import com.shanghe.house.entity.Device;
import com.shanghe.house.entity.Timer;
import com.shanghe.house.exception.BusinessException;
import com.shanghe.house.mapper.TimerMapper;
import com.shanghe.house.util.TimeUtils;
import com.shanghe.house.vo.TimerVO;

/**
 * 定时任务服务类
 * 提供定时任务相关的业务逻辑处理，包括任务的CRUD操作和调度管理
 */
@Service
public class TimerService extends ServiceImpl<TimerMapper, Timer> {
    private final DeviceService deviceService;

    public TimerService(DeviceService deviceService) {
        this.deviceService = deviceService;
    }

    public List<Timer> list() {
        List<Timer> timers = super.list();
        // 转换所有定时任务的时间格式
        timers.forEach(this::convertToMinutes);
        return timers;
    }

    public Timer getById(Long id) {
        Timer timer = super.getById(id);
        if (timer != null) {
            convertToMinutes(timer);
        }
        return timer;
    }

    @Transactional
    public Timer create(TimerDTO timerDTO) {
        validateTimer(timerDTO);
        Timer timer = new Timer();
        BeanUtils.copyProperties(timerDTO, timer);
        timer.setCronExpression(TimeUtils.minutesToCron(timerDTO.getIntervalMinutes()));
        save(timer);
        return timer;
    }

    @Transactional
    public Timer update(Long id, TimerDTO timerDTO) {
        Timer timer = getById(id);
        if (timer == null) {
            throw new RuntimeException("定时任务不存在");
        }
        // 如果不是更新同一个设备的任务，需要重新验证
        if (!timer.getDeviceId().equals(timerDTO.getDeviceId())) {
            validateTimer(timerDTO);
        }
        BeanUtils.copyProperties(timerDTO, timer);
        timer.setCronExpression(TimeUtils.minutesToCron(timerDTO.getIntervalMinutes()));
        updateById(timer);
        return timer;
    }

    @Transactional
    public void delete(Long id) {
        Timer timer = getById(id);
        if (timer == null) {
            throw new RuntimeException("定时任务不存在");
        }
        removeById(id);
    }

    @Transactional
    public void updateDeviceStatus(Long deviceId, Boolean status) {
        deviceService.lambdaUpdate()
                .set(Device::getStatus, status)
                .eq(Device::getId, deviceId)
                .update();
    }

    public Timer findById(Long id) {
        return getById(id);
    }

    public List<Timer> findAll() {
        return list();
    }

    private void validateTimer(TimerDTO timerDTO) {
        // 验证设备是否存在
        Device device = deviceService.getById(timerDTO.getDeviceId());
        if (device == null) {
            throw new RuntimeException("设备不存在");
        }
        // 验证执行间隔
        if (timerDTO.getIntervalMinutes() <= 0 || timerDTO.getIntervalMinutes() > 1440) {
            throw new RuntimeException("执行间隔必须在1-1440分钟之间");
        }
        // 验证设备是否已有相同的定时任务
        boolean exists = lambdaQuery()
                .eq(Timer::getDeviceId, timerDTO.getDeviceId())
                .eq(Timer::getTargetStatus, timerDTO.getTargetStatus())
                .eq(Timer::getStatus, true)
                .exists();
        if (exists) {
            throw new RuntimeException("该设备已存在相同状态的定时任务");
        }
    }

    /**
     * 将Timer对象的cron表达式转换为分钟显示
     */
    private void convertToMinutes(Timer timer) {
        try {
            timer.setIntervalMinutes(TimeUtils.cronToMinutes(timer.getCronExpression()));
        } catch (Exception e) {
            // 如果转换失败，设置为0
            timer.setIntervalMinutes(0);
        }
    }

    /**
     * 获取定时任务详情，包括下一次执行时间
     */
    public TimerVO getTimerDetail(Long id) {
        Timer timer = getById(id);
        if (timer == null) {
            throw new RuntimeException("定时任务不存在");
        }

        TimerVO timerVO = new TimerVO();
        BeanUtils.copyProperties(timer, timerVO);
        timerVO.setIntervalMinutes(timer.getIntervalMinutes());
        timerVO.setNextExecuteTime(
                CronExpression.parse(timer.getCronExpression())
                        .next(LocalDateTime.now())
        );

        // 添加设备信息
        Device device = deviceService.getById(timer.getDeviceId());
        if (device != null) {
            timerVO.setDeviceName(device.getName());
            timerVO.setDeviceType(device.getType());
            timerVO.setDeviceLocation(device.getLocation());
        }

        return timerVO;
    }

    /**
     * 切换定时任务状态
     */
    @Transactional
    public Timer toggleStatus(Long id) {
        Timer timer = getById(id);
        if (timer == null) {
            throw new BusinessException(404, "定时任务不存在");
        }
        
        // 切换状态
        timer.setStatus(!timer.getStatus());
        updateById(timer);
        
        return timer;
    }

    /**
     * 批量更新定时任务状态
     */
    @Transactional
    public void batchUpdateStatus(List<Long> ids, boolean status) {
        if (ids == null || ids.isEmpty()) {
            return;
        }
        
        lambdaUpdate()
            .set(Timer::getStatus, status)
            .in(Timer::getId, ids)
            .update();
    }

    /**
     * 检查定时任务是否存在
     */
    public void checkTimerExists(Long id) {
        if (!lambdaQuery().eq(Timer::getId, id).exists()) {
            throw new BusinessException(404, "定时任务不存在");
        }
    }

    /**
     * 获取设备的所有定时任务
     */
    public List<Timer> getDeviceTimers(Long deviceId) {
        return lambdaQuery()
                .eq(Timer::getDeviceId, deviceId)
                .eq(Timer::getStatus, true)
                .list();
    }

    /**
     * 禁用设备的所有定时任务
     */
    @Transactional
    public void disableDeviceTimers(Long deviceId) {
        lambdaUpdate()
            .set(Timer::getStatus, false)
            .eq(Timer::getDeviceId, deviceId)
            .update();
    }
}